<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.0.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/wang-cheng/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/wang-cheng/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/wang-cheng/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/wang-cheng/images/logo.svg" color="#222">

<link rel="stylesheet" href="/wang-cheng/css/main.css">


<link rel="stylesheet" href="/wang-cheng/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"cheng-wang123.gitee.io","root":"/wang-cheng/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta name="description" content="Spring事务的实现方式和原理以及隔离级别在使用Spring框架时，有两种事务实现方式：一种是编程式，一种是声明式，@Transactiuon注解是声明式。 首先，事务这个概念是数据库层面的，Spring只是基于数据库中的事务进行了扩展，以及提供了一些能让程序员更加方便操作事务的方式 在一个方法上加@Transaction，Spring会基于这个注解生成一个代理对象，将代理对象作为这个类的bea">
<meta property="og:type" content="article">
<meta property="og:title" content="面试题(五)">
<meta property="og:url" content="https://cheng-wang123.gitee.io/wang-cheng/2022/03/22/%E9%9D%A2%E8%AF%95%E9%A2%98-%E4%BA%94/index.html">
<meta property="og:site_name" content="诚の博客">
<meta property="og:description" content="Spring事务的实现方式和原理以及隔离级别在使用Spring框架时，有两种事务实现方式：一种是编程式，一种是声明式，@Transactiuon注解是声明式。 首先，事务这个概念是数据库层面的，Spring只是基于数据库中的事务进行了扩展，以及提供了一些能让程序员更加方便操作事务的方式 在一个方法上加@Transaction，Spring会基于这个注解生成一个代理对象，将代理对象作为这个类的bea">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://cheng-wang123.gitee.io/wang-cheng/2022/03/22/%E9%9D%A2%E8%AF%95%E9%A2%98-%E4%BA%94/SpringMVC%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.jpg">
<meta property="og:image" content="https://cheng-wang123.gitee.io/wang-cheng/2022/03/22/%E9%9D%A2%E8%AF%95%E9%A2%98-%E4%BA%94/%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E6%B5%81%E7%A8%8B.jpg">
<meta property="og:image" content="https://cheng-wang123.gitee.io/wang-cheng/2022/03/22/%E9%9D%A2%E8%AF%95%E9%A2%98-%E4%BA%94/%E6%96%B0%E7%94%9F%E4%BB%A3%E5%92%8C%E8%80%81%E5%B9%B4%E4%BB%A3GC.png">
<meta property="article:published_time" content="2022-03-22T02:55:26.000Z">
<meta property="article:modified_time" content="2022-05-03T08:45:59.967Z">
<meta property="article:author" content="王诚">
<meta property="article:tag" content="面试题">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://cheng-wang123.gitee.io/wang-cheng/2022/03/22/%E9%9D%A2%E8%AF%95%E9%A2%98-%E4%BA%94/SpringMVC%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.jpg">

<link rel="canonical" href="https://cheng-wang123.gitee.io/wang-cheng/2022/03/22/%E9%9D%A2%E8%AF%95%E9%A2%98-%E4%BA%94/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>面试题(五) | 诚の博客</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/wang-cheng/atom.xml" title="诚の博客" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/wang-cheng/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">诚の博客</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">记录学习中的点点滴滴</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/wang-cheng/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/wang-cheng/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/wang-cheng/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/wang-cheng/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://cheng-wang123.gitee.io/wang-cheng/2022/03/22/%E9%9D%A2%E8%AF%95%E9%A2%98-%E4%BA%94/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/wang-cheng/images/avatar.gif">
      <meta itemprop="name" content="王诚">
      <meta itemprop="description" content="命运对勇士低语，你无法抵御风暴；勇士低声回应，我就是风暴">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="诚の博客">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          面试题(五)
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2022-03-22 10:55:26" itemprop="dateCreated datePublished" datetime="2022-03-22T10:55:26+08:00">2022-03-22</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2022-05-03 16:45:59" itemprop="dateModified" datetime="2022-05-03T16:45:59+08:00">2022-05-03</time>
              </span>

          
            <span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv" style="display: none;">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span id="busuanzi_value_page_pv"></span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h2 id="Spring事务的实现方式和原理以及隔离级别"><a href="#Spring事务的实现方式和原理以及隔离级别" class="headerlink" title="Spring事务的实现方式和原理以及隔离级别"></a><strong>Spring事务的实现方式和原理以及隔离级别</strong></h2><p>在使用Spring框架时，有两种事务实现方式：一种是编程式，一种是声明式，@Transactiuon注解是声明式。</p>
<p>首先，事务这个概念是数据库层面的，Spring只是基于数据库中的事务进行了扩展，以及提供了一些能让程序员更加方便操作事务的方式</p>
<p>在一个方法上加@Transaction，Spring会基于这个注解生成一个代理对象，将代理对象作为这个类的bean。在使用代理对象时，如果存在这个注解，会将事务的自动提交设置为false(默认是true)，再去执行原本的逻辑方法。如果逻辑方法没有异常，那么代理逻辑会将事务进行提交，如果出现异常，会将事务进行回滚。</p>
<p>当然，针对哪些异常回滚事务是可以配置的，可以利用@Transaction注解中的rollbackFor属性进行配置，默认情况下会对RuntimeException和Error进行回滚。(不会将异常给catch掉)</p>
<p>Spring事务的隔离级别就是数据库的隔离级别：外加一个默认级别</p>
<ul>
<li><p>read uncommitted 未提交读</p>
</li>
<li><p>read committed 提交读、不可重复读</p>
</li>
<li><p>repeatable read 可重复读</p>
</li>
<li><p>serializable 可串行化</p>
</li>
</ul>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">数据库的配置隔离级别是<span class="keyword">Read</span> Commited,而Spring配置的隔离级别是<span class="keyword">Repeatable</span> <span class="keyword">Read</span>，请问这时隔离级别是以哪一个为准</span><br><span class="line">以Spring配置的为准，如果Spring设置的隔离级别数据库不支持，效果取决于数据库</span><br></pre></td></tr></table></figure>
<h2 id="脏读、不可重复读、幻读"><a href="#脏读、不可重复读、幻读" class="headerlink" title="脏读、不可重复读、幻读"></a><strong>脏读、不可重复读、幻读</strong></h2><p><strong>脏读</strong>：一个事务读取了另一个事务还没提交(回滚)的事务</p>
<p><strong>不可重复读</strong>：两次查询同一条数据有不同的结果，因为其他事务可能在<code>UPDATE</code>操作</p>
<p><strong>幻读</strong>：事务B根据条件查询到N条数据，但是这时事务A<code>INSERT</code>或<code>DELETE</code>了M条符合事务B查询条件的数据。事务B再次查询结果就和上一次不一致了，得到了N+M条数据</p>
<p>脏读是select操作，查询到了脏数据</p>
<p>不可重复读通常是其他线程发生了update操作，再次读取结果与上一次不同</p>
<p>幻读通常是其他线程发生了insert 或 delete操作，再次读取结果与上一次不同</p>
<p><strong>丢失更新</strong>：丢失更新指两个事务同时更新一行数据，后提交（或撤销）的事务将之前事务提交的数据覆盖了。</p>
<p>丢失更新可分为两类，分别是第一类丢失更新和第二类丢失更新。</p>
<ul>
<li><p>第一类丢失更新是指两个事务同时操作同一个数据时，当第一个事务撤销时，把已经提交的第二个事务的更新数据覆盖了，第二个事务就造成了数据丢失。</p>
</li>
<li><p>第二类丢失更新是指当两个事务同时操作同一个数据时，第一个事务将修改结果成功提交后，对第二个事务已经提交的修改结果进行了覆盖，对第二个事务造成了数据丢失。</p>
</li>
</ul>
<h2 id="MySQL四种隔离级别"><a href="#MySQL四种隔离级别" class="headerlink" title="MySQL四种隔离级别"></a><strong>MySQL四种隔离级别</strong></h2><p><strong>读未提交(一级封锁协议)</strong>：本质是在事务A中修改完数据M后，立刻对这个数据M加上共享锁(S锁)[当事务A继续修改数据M的时候，先释放掉S锁，再修改数据，再加上S锁]，根据S锁的特性，事务B可以读到事务A修改后的数据(无论事务A是否提交，因为是共享锁，随时随地都能查到数据A修改后的结果)，事务B不能去修改数据M，直到事务A提交，释放掉S锁。</p>
<p>缺点：可能会造成丢失更新、脏读、不可重复读、幻读</p>
<p><strong>读已提交(二级封锁协议)</strong>：本质是事务A在修改数据M后立刻加X锁，事务B不能修改数据M，同时不能查询到最新的数据M(避免脏读)，查询到的数据M是上一个版本(Innodb MVCC快照)的。</p>
<p>优点：避免脏读</p>
<p>缺点：可能会造成丢失更新、不可重复读、幻读</p>
<p><strong>可重复读(三级封锁协议)</strong>：本质是二级封锁协议基础上，对<strong>读到的数据M</strong>瞬间加上共享锁，直到事务结束才释放（保证了其他事务没办法修改该数据），这个级别是MySql 5.5 默认的隔离级别。</p>
<p>优点：避免脏读、不可重复读</p>
<p>缺点：可能会造成丢失更新、幻读。</p>
<p><strong>序列化(最强封锁协议)</strong>：本质是从MVCC并发控制退化到基于锁的并发控制，对事务中所有读取操作加S锁，写操作加X锁，这样可以避免脏读，不可重复读，幻读，更新丢失，开销也最大，会造成读写冲突，并发程度也最低。</p>
<h2 id="Spring事务传播机制"><a href="#Spring事务传播机制" class="headerlink" title="Spring事务传播机制"></a><strong>Spring事务传播机制</strong></h2><p>多个事务相互调用时，事务如何在这些方法间传播<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">方法<span class="selector-tag">A</span>是一个事务方法，方法<span class="selector-tag">A</span>执行过程中调用了方法<span class="selector-tag">B</span>，那么方法<span class="selector-tag">B</span>有无事务以及方法<span class="selector-tag">B</span>对事务的要求不同都会对方法<span class="selector-tag">A</span>的事务具体执行造成影响，同时方法<span class="selector-tag">A</span>的事务对方法<span class="selector-tag">B</span>的事务执行也有影响，这种影响具体是什么就由两个方法所定义的事务传播类型所决定。</span><br></pre></td></tr></table></figure></p>
<p>@Transaction()注解内的可选项</p>
<p>REQUIRED(Spring默认的事务传播类型):如果当前(调用方)没有事务，则自己(被调用方)新建一个事务，如果当前存在事务，则加入这个事务(这个事务内所有SQL要么一起成功，要么一起失败)</p>
<p>SUPPORTS:当前存在事务，则加入当前事务，当前没有事务，就以非事务方法执行</p>
<p>MANDATORY:当前存在事务，则加入当前事务，如果当前没有事务，则抛出异常</p>
<p>REQUIRES_NEW:创建一个新事务，当前存在事务，则挂起该事务(当前的事务挂起，自己的事务先处理，处理话再处理当前的事务。就是自己处理自己的事务)</p>
<p>NOT_SUPPORTED:以非事务方式执行(自己一定是非事务运行，不要事务)，如果当前存在事务，则挂起当前事务(当前的事务，在自己的逻辑处理完成后，再处理)</p>
<p>NEVER:不使用事务，如果当前事务存在，则抛出异常</p>
<p>NESTED:如果当前存在事务，则在嵌套事务中执行，否则REQUIRED的操作一样(开启一个事务)<br><figure class="highlight oxygene"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">和REQUIRES_NEW对比：</span><br><span class="line">REQUIRES_NEW是新建一个事务并且新开启的这个事务与原事务无关。而<span class="keyword">NESTED</span>则是当前存在事务时(我们把当前事务称之为父事务)会开启一个嵌套事务(称之为子事务)。在<span class="keyword">NESTED</span>情况下父事务回滚时，子事务也回滚，而在REQUIRES_NEW情况下，原有事务回滚，不会影响新开启的事务</span><br><span class="line"></span><br><span class="line">和REQUIRED区别：</span><br><span class="line">REQUIRED情况下，调用方存在事务时，则被调用方和调用方使用同一事务，那么被调用方出现异常时，由于共用一个事务，所以无论调用方是否catch其异常，事务都会回滚，而在<span class="keyword">NESTED</span>情况下，被调用方发生异常时，调用方可以catch其异常，这样具有子事务回滚，父事务不受影响</span><br></pre></td></tr></table></figure></p>
<h2 id="Spring事务什么时候会失效"><a href="#Spring事务什么时候会失效" class="headerlink" title="Spring事务什么时候会失效"></a><strong>Spring事务什么时候会失效</strong></h2><p>Spring事务的原理是AOP，进行了切面增强，那么失效的根本原因是这个AOP不起作用了！常见的情况有如下几种：</p>
<p>1、发生自调用，类里面使用this调用本类的方法(this通常省略)，此时这个this对象不是代理类(使用getBean()获取到的才是代理对象)，而是UserService本身！</p>
<p>解决方法很简单，让那个this变成UserService的代理类即可(使用被@Autowire注入的对象去调)</p>
<p>2、方法不是public的</p>
<figure class="highlight aspectj"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Transaction</span>只能用于<span class="keyword">public</span>方法上，否则事务不会失效，如果要用在非<span class="keyword">public</span>上，可以开启AspectJ代理模式</span><br></pre></td></tr></table></figure>
<p>3、数据库不支持事务</p>
<p>4、没有被Spring管理(没有例如@Service这样的注解，没有将这个类放入IOC容器)</p>
<p>5、异常被吃掉(catch)，事务不会回滚(或者抛出的异常没有被定义，默认为RuntimeException)</p>
<h2 id="什么是bean的自动装配，有哪些方式"><a href="#什么是bean的自动装配，有哪些方式" class="headerlink" title="什么是bean的自动装配，有哪些方式"></a><strong>什么是bean的自动装配，有哪些方式</strong></h2><p>自动装配，只需要在xml配置文件<code>&lt;bean&gt;</code>中定义<code>autowire</code>属性<br><figure class="highlight abnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;bean id <span class="operator">=</span> customer class <span class="operator">=</span> <span class="string">&quot;com.xxx.xxx.Customer&quot;</span> autowire<span class="operator">=</span><span class="string">&quot;&quot;</span>/&gt;</span><br></pre></td></tr></table></figure><br><code>autowire</code>属性有五种装配方式</p>
<ul>
<li><p>no - 缺省值装配，自动配置是通过ref属性手动设置的</p>
<figure class="highlight angelscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">手动装配:以value或<span class="built_in">ref</span>的方式明确指定属性值都是手动装配</span><br><span class="line">需要通过<span class="built_in">ref</span>属性来连接bean</span><br></pre></td></tr></table></figure>
</li>
<li><p>byName - 根据bean的属性名称进行自动装配</p>
<figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Customer的属性名称为person，Spring会将bean <span class="keyword">id</span>为person的bean通过<span class="keyword">setter</span>方法进行自动装配。</span><br><span class="line">&lt;bean <span class="keyword">id</span> = <span class="string">&quot;person&quot;</span> <span class="keyword">class</span> = <span class="string">&quot;com.xxx.xxx.Person&quot;</span>/&gt;</span><br><span class="line">&lt;bean <span class="keyword">id</span> = <span class="string">&quot;customer&quot;</span> <span class="keyword">class</span> = <span class="string">&quot;com.xxx.xxx.Customer&quot;</span> autowire = <span class="string">&quot;byName&quot;</span>/&gt;</span><br></pre></td></tr></table></figure>
</li>
<li><p>byType - 根据bean类型进行自动装配</p>
<figure class="highlight abnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Customer的属性person的类型为Person，Spring会将Person类型通过setter方法进行自动装配</span><br><span class="line">&lt;bean id <span class="operator">=</span> <span class="string">&quot;customer&quot;</span> class <span class="operator">=</span> <span class="string">&quot;com.xxx.xxx.Customer&quot;</span> autowire <span class="operator">=</span> <span class="string">&quot;byType&quot;</span>/&gt;</span><br><span class="line">&lt;bean id <span class="operator">=</span> <span class="string">&quot;person&quot;</span> class <span class="operator">=</span> <span class="string">&quot;com.xxx.xxx.Person&quot;</span>/&gt;</span><br></pre></td></tr></table></figure>
</li>
<li><p>constructor - 类似byType，不过是应用于构造器的参数。如果一个bean与构造器参数的类型形同，则进行自动配置，否则导致异常</p>
<figure class="highlight abnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Custoemr构造函数的参数person的类型为Person，Spring会将Person类型通过构造方法进行自动装配</span><br><span class="line">&lt;bean id <span class="operator">=</span> <span class="string">&quot;customer&quot;</span> class <span class="operator">=</span> <span class="string">&quot;com.xxx.xxx.Customer&quot;</span> autowire <span class="operator">=</span> <span class="string">&quot;constructor&quot;</span>/&gt;</span><br><span class="line">&lt;bead id <span class="operator">=</span> <span class="string">&quot;person&quot;</span> class <span class="operator">=</span> <span class="string">&quot;com.xxx.xxx.Person&quot;</span>/&gt;</span><br></pre></td></tr></table></figure>
</li>
<li><p>autodetect - 如果有默认的构造器，则通过constructor方式进行自动装配，否则使用byType方式进行自动装配</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">如果有默认的构造器，则通过contructor方式进行自动装配，否则使用byType方式进行自动装配</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>@Autowired自动装配bean，可以在字段、setter方法、构造函数上使用。</p>
<h2 id="Spring-Boot、SpringMVC和Spring有什么区别"><a href="#Spring-Boot、SpringMVC和Spring有什么区别" class="headerlink" title="Spring Boot、SpringMVC和Spring有什么区别"></a><strong>Spring Boot、SpringMVC和Spring有什么区别</strong></h2><p>Spring是一个IOC容器，用来管理bean，使用依赖注入实现控制反转，可以很方便的整合各种框架，提供AOP机制你补OOP的代码重复问题、更方便将不同类不同方法中的共同处理抽取成切面、自动注入给方法执行，比如日志、异常等</p>
<p>SpringMVC是Spring对web框架的一个解决方案，提供了一个总的前端控制器Servlet，用来接收请求，然后定义了一套路由(url和handle的映射)以及适配执行handle，将handle结果使用视图解析技术生成视图展示给前端</p>
<p>SpringBoot是Spring提供的一个快速开发工具包，让程序员能更方便、更快速的开发Spring+SpringMVC应用，简化了配置(约定了默认配置)，整合了一系列的解决方案(starter机制)、redis、mongodb、es，可以开箱即用</p>
<h2 id="Spring-MVC工作流程"><a href="#Spring-MVC工作流程" class="headerlink" title="Spring MVC工作流程"></a><strong>Spring MVC工作流程</strong></h2><ol>
<li><p>用户发送请求至前端控制器DispatcherServlet</p>
</li>
<li><p>DispatcherServlet收到请求调用HanlerMapping处理器映射器(维护url到handle的一个映射关系)</p>
</li>
<li><p>处理器映射器找到具体的处理器(可以根据xml配置、注解查找)，生成处理器以及拦截器(如果有则生成)一并返回给DispatcherServlet</p>
</li>
<li><p>DispatcherServlet调用HandlerAdapter处理器适配器(适配器调用support方法判断Controller类是用什么实现的(实现Controller接口、@Controller、继承Servlet)，根据Controller实现方式不同，进行不同的处理)</p>
</li>
<li><p>HandlerAdapter经过适配调用具体的处理器(Controller，也叫后端控制器)</p>
</li>
<li><p>Controller执行完成返回ModelAndView</p>
</li>
<li><p>HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet</p>
</li>
<li><p>DispatcherServlet将ModelAndView解析后传给ViewResolver视图解析器</p>
</li>
<li><p>ViewResolver解析后返回具体view</p>
</li>
<li><p>DispatcherServlet根据view进行渲染视图(即将模型数据填充至视图中)</p>
</li>
<li><p>DispatcherServlet响应用户</p>
</li>
</ol>
<img src="/wang-cheng/2022/03/22/%E9%9D%A2%E8%AF%95%E9%A2%98-%E4%BA%94/SpringMVC%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.jpg" class title="SpringMVC执行流程">
<h2 id="SpringMVC的主要组件-九大组件"><a href="#SpringMVC的主要组件-九大组件" class="headerlink" title="SpringMVC的主要组件(九大组件)"></a><strong>SpringMVC的主要组件(九大组件)</strong></h2><p>Handler：也就是处理器。它直接对应着MVC中的C，也就是Controller层，它的具体表现形式有很多，可以是类，也可以是方法。在Controller层中@RequestMapping标注的所有地方都可以看成是一个Handler，只要可以实际处理请求就可以是Handler</p>
<p>1、HandlerMapping(维护了url到handler的一个映射关系<url,handler>)</url,handler></p>
<p>initHandlerMappings(context)，处理器映射器，根据用户请求的资源uri来查找Handler的。在SpringMVC中会有很多请求，每个请求都需要一个Handler处理，具体接收到一个请求后使用哪个Handler处理，这就是HandlerMapping需要做的事(DispatcherServlet接到请求以后会遍历处理器映射器，找每一个处理器映射器里面所维护的map<url,handler>，如果找到了相同的url，就证明找到了处理器)</url,handler></p>
<p>2、HandlerAdapter</p>
<p>initHandlerAdapters(context)，适配器。因为SpringMVC中的Handler可以是任意形式的，只要能处理请求就ok，但是Servlet需要的处理方法的结构却是固定的，都是以request和response为参数的方法。如何让固定的Servlet处理方法调用灵活的Handler来进行处理呢，这就是HandlerAdapter需要做的事。Handler是用来干活的工具；HandlerMapping用于根据需要干的活找到相应的工具；HandlerAdapter是使用工具的人。</p>
<p>3、HandlerExceptionResolver</p>
<p>initHandlerExceptionResolver(context)，其他组件都是用来干活的。在干活过程中难免会出现问题，出问题后怎么办呢？这就需要一个专门的角色对异常进行处理，在SpringMVC中就是HandlerExceptionResolver，具体来说，此组件的作用是根据异常设置ModelAndView，之后再交给render方法进行渲染</p>
<p>4、ViewResolver</p>
<p>initViewResolver(context)，视图解析器，ViewResolver用来将String类型的视图名和Locale解析为View类型的视图。View是用来渲染页面的，也就是将程序返回的参数填入模板里，生成html(也可以是其他文件)文件。这里就有两个关键问题：使用哪个模板？用什么技术(规则)填入参数？这其实是ViewResolver主要要做的工作，ViewResolver需要找到渲染所用的模板和所用的技术(也就是视图的类型)进行渲染，具体的渲染过程则交由不同的视图自己完成。</p>
<p>5、RequestToViewNameTranslator</p>
<p>6、LocaleResolver </p>
<p>SpringMVC主要有两个地方用到了Locale：一是ViewResolver视图解析的时候，二是用到国际化资源或者主题的时候</p>
<p>7、ThemeResolver</p>
<p>用于解析主题 </p>
<p>8、MultipartResolver</p>
<p>用于处理文件上传请求。处理方法是将普通的request包装成MultipartHttpServletRequest，后者可以直接调用getFile方法获取File，如果上传多个文件，还可以调用getFileMap得到FileName—-&gt;File结构的map。一共三个方法，分别是判断是不是上传请求、将request包装成MultipartHttpServletRequest、处理完后清理上传过程中产生的临时资源</p>
<p>9、FlashMapManager</p>
<p>initFlashMapManager(context)，用来管理FlashMap的，FlashMap主要用在redirect中传递参数</p>
<h2 id="Spring-Boot自动配置原理"><a href="#Spring-Boot自动配置原理" class="headerlink" title="Spring Boot自动配置原理"></a><strong>Spring Boot自动配置原理</strong></h2><p>@Import + @Configuration + Spring spi</p>
<p>自动装配类是由各个starter提供，使用@Configuration + @Bean定义配置类，放到META-INF/spring.factories下使用spring spi扫描META-INF/spring.factories下的配置类</p>
<img src="/wang-cheng/2022/03/22/%E9%9D%A2%E8%AF%95%E9%A2%98-%E4%BA%94/%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E6%B5%81%E7%A8%8B.jpg" class title="自动配置流程">
<h2 id="如何理解SpringBoot中的Starter"><a href="#如何理解SpringBoot中的Starter" class="headerlink" title="如何理解SpringBoot中的Starter"></a><strong>如何理解SpringBoot中的Starter</strong></h2><p>在使用Spring+SpringMVC开发时，如果需要引入mybatis等框架，需要到xml中定义mybatis需要的bean</p>
<p>starter就是定义一个starter的jar包，写一个@Configuration配置类，将这些bean定义在里面，然后在starter包的META-INF/spring.factories中写入该配置类，springboot会按照约定来加载该配置类</p>
<p>开发人员只需要将相应的starter包依赖进应用，进行相应的属性配置(使用默认配置时，不需要配置)，就可以直接进行代码开发，使用对应的功能，比如mybatis-spring-boot-starter,spring-boot-starter-redis</p>
<h2 id="什么是嵌入式服务器，为什么要使用嵌入式服务器"><a href="#什么是嵌入式服务器，为什么要使用嵌入式服务器" class="headerlink" title="什么是嵌入式服务器，为什么要使用嵌入式服务器"></a><strong>什么是嵌入式服务器，为什么要使用嵌入式服务器</strong></h2><p>节省了下载安装tomcat，应用也不需要再打war包，然后放到webapp目录下再运行</p>
<p>只需要一个安装了java的虚拟机，就可以直接在上面部署应用程序了</p>
<p>springboot已经内置了tomcat.jar，运行main方法时会去启动tomcat，并利用tomcat的spi机制加载springmvc。</p>
<h2 id="Jar包和War包的区别"><a href="#Jar包和War包的区别" class="headerlink" title="Jar包和War包的区别"></a><strong>Jar包和War包的区别</strong></h2><p><strong>什么是jar包?</strong></p>
<p>jar包是类的归档文件，jar文件格式以流行的ZIP文件格式作为基础，和ZIP文件不一样的是，JAR文件不仅仅用来进行压缩和发布，还用来部署和封装库、组件以及插件程序，并且，还能够被像编译器以及JVM这样的工具直接使用。</p>
<p><strong>什么是war包?</strong></p>
<p>war包是JavaWeb程序打的包，war包当中包含写的代码编译成的class文件，依赖的包，配置文件，所有的网站页面，包括html，jsp等等。可以将一个war包理解成一个web项目，里面是项目的所有东西。</p>
<p>目录结构：</p>
<ul>
<li><p>jar包当中的com里面放的是class文件，配置文件，可是没有静态资源的文件,大部分的JAR里面，含有一个META-INF目录，它是用来存储包和扩展的配置数据的，例如，安全性和版本信息。</p>
</li>
<li><p>war包当中的WEB-INF里放的class文件和配置文件，META-INF和jar包作用一样，war包里面还包含静态资源的文件。</p>
</li>
</ul>
<p>jar包和war包的不同之处：</p>
<ul>
<li><p>war包和项目的文件结构保持一致，而jar包却不一样;</p>
</li>
<li><p>jar包里面没有静态资源的文件;</p>
</li>
</ul>
<p>部署项目的区别</p>
<p>部署普通的spring项目用war包就可以，部署springboot项目用jar包就可以，因为springboot内置tomcat。</p>
<h2 id="SSRF"><a href="#SSRF" class="headerlink" title="SSRF"></a><strong>SSRF</strong></h2><p>概念：SSRF为服务端请求伪造(Server-Side Request Forgery),指的是攻击者在未能取得服务器所有权限时，利用服务器漏洞以服务器的身份发送一条构造好的请求给服务器所在内网。SSRF攻击通常针对外部网络无法直接访问的内部系统。 </p>
<p>原理：很多web应用都提供了从其他的服务器上获取数据的功能。使用指定的URL，web应用便可以获取图片，下载文件，读取文件内容等。SSRF的实质是利用存在缺陷的web应用作为代理攻击远程和本地的服务器。一般情况下， SSRF攻击的目标是外网无法访问的内部系统，黑客可以利用SSRF漏洞获取内部系统的一些信息（正是因为它是由服务端发起的，所以它能够请求到与它相连而与外网隔离的内部系统）。SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。</p>
<p>主要攻击方式：攻击者想要访问主机B上的服务，但是由于存在<em>*</em>或者主机B是属于内网主机等原因导致攻击者无法直接访问主机B。而服务器A存在SSRF漏洞，这时攻击者可以借助服务器A来发起SSRF攻击，通过服务器A向主机B发起请求，从而获取主机B的一些信息。</p>
<h2 id="CSRF"><a href="#CSRF" class="headerlink" title="CSRF"></a><strong>CSRF</strong></h2><p>跨站请求伪造（英语：Cross-site request forgery），也被称为 one-click attack 或者 session riding，通常缩写为 CSRF或者 XSRF， 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨网站脚本（XSS）相比，XSS 利用的是用户对指定网站的信任，CSRF 利用的是网站对用户网页浏览器的信任。 </p>
<h2 id="AOP中术语描述"><a href="#AOP中术语描述" class="headerlink" title="AOP中术语描述"></a><strong>AOP中术语描述</strong></h2><ol>
<li><p>连接点（Joinpoint）:连接点描述的是程序执行的某个特定位置。如一个类的初始化前、初始化后，或者类的某个方法调用前、调用后、方法抛出异常后等等。一个类或一段程序代码拥有一些具有边界性质的特定点，这些特定点就称为连接点。连接点用来定义在目标程序的哪里通过AOP加入新的逻辑。Spring仅支持方法的连接点，即仅能在方法调用前、方法调用后、方法抛出异常时以及方法调用前后这些程序执行点织入增强。<br>连接点由两个信息确定：第一是用方法表示的程序执行点；第二是用相对点表示的方位。<br>执行点：即程序执行流程中的某个点。如执行某个语句或者语句块、执行某个方法、装载某个类、抛出某个异常……</p>
</li>
<li><p>切入点（Pointcut）:切入点是一个连接点的过滤条件，AOP 通过切点定位到特定的连接点。每个类都拥有多个连接点：例如 UserService类中的所有方法实际上都是连接点，即连接点是程序类中客观存在的事物。类比：连接点相当于数据库中的记录，切点相当于查询条件。切点和连接点不是一对一的关系，一个切点匹配多个连接点，切点通过 org.springframework.aop.Pointcut 接口进行描述，它使用类和方法作为连接点的查询条件。</p>
</li>
<li><p>通知（Advice）:切面在某个具体的连接点采取的行为或行动，称为通知。切面的核心逻辑代码都写在通知中，有人也称之为增强或者横切关注点。通知是切面功能的具体实现，通常是业务代码以外的需求，如日志、验证等，这些被模块化的特殊对象。常用的通知接口有:</p>
<ul>
<li><p>前置通知：org.springframework.aop.MethodBeforeAdvice</p>
</li>
<li><p>后置通知：org.springframework.aop.AfterReturningAdvice</p>
</li>
<li><p>异常通知：org.springframework.aop.ThrowsAdvice</p>
</li>
<li><p>该接口没有要实现的方法，需要自定义一个afterThrowing()方法。</p>
</li>
<li><p>环绕通知：org.aopalliance.intercept.MethodInterceptor</p>
</li>
</ul>
</li>
<li><p>通知器（Advisor）:通知器由一个切入点（pointcut）和一个通知（Advice）组成。通知就是增强的那部分功能代码，如记录日志代码、控制权限代码。</p>
</li>
<li><p>切面（Aspect）:与通知器（advisor）类似都是通知+切入点。区别在于，切面中的类无需实现通知接口，但需要在配置文件中指定类中的方法名；而通知器仅需指定类名即可，因为通知器中的类都实现了通知接口，很明确的知道通知方法是哪个。</p>
</li>
<li><p>目标(Target):被通知的对象（方法）</p>
</li>
<li><p>代理(Proxy):向目标对象应用通知之后创建的对象</p>
</li>
</ol>
<h2 id="GC中的新生代、老年代垃圾收集器"><a href="#GC中的新生代、老年代垃圾收集器" class="headerlink" title="GC中的新生代、老年代垃圾收集器"></a><strong>GC中的新生代、老年代垃圾收集器</strong></h2><img src="/wang-cheng/2022/03/22/%E9%9D%A2%E8%AF%95%E9%A2%98-%E4%BA%94/%E6%96%B0%E7%94%9F%E4%BB%A3%E5%92%8C%E8%80%81%E5%B9%B4%E4%BB%A3GC.png" class title="新生代和老年代GC">
<h2 id="Java程序初始化三个原则"><a href="#Java程序初始化三个原则" class="headerlink" title="Java程序初始化三个原则"></a><strong>Java程序初始化三个原则</strong></h2><ol>
<li><p>静态对象（变量）优先于非静态对象（变量）初始化，其中静态对象（变量）初始化一次，非静态对象（变量）可能会初始化多次。</p>
</li>
<li><p>父类优先于子类初始化</p>
</li>
<li><p>按照成员变量定义顺序初始化，即使变量定义与方法定义中，依然在被调用前初始化。</p>
</li>
</ol>
<h2 id="Java初始化-类加载-顺序"><a href="#Java初始化-类加载-顺序" class="headerlink" title="Java初始化(类加载)顺序"></a><strong>Java初始化(类加载)顺序</strong></h2><ol>
<li><p>父类静态变量</p>
</li>
<li><p>父类静态代码块</p>
</li>
<li><p>子类静态变量</p>
</li>
<li><p>子类静态代码块</p>
</li>
<li><p>父类非静态变量</p>
</li>
<li><p>父类非静态代码块</p>
</li>
<li><p>父类构造函数</p>
</li>
<li><p>子类非静态变量</p>
</li>
<li><p>子类非静态代码块</p>
</li>
<li><p>子类构造函数</p>
</li>
</ol>
<h2 id="java类的初始化和实例化区别"><a href="#java类的初始化和实例化区别" class="headerlink" title="java类的初始化和实例化区别"></a><strong>java类的初始化和实例化区别</strong></h2><p>类的初始化：是完成程序执行前的准备工作。在这个阶段，静态的（变量，方法，代码块）会被执行。同时在会开辟一块存储空间用来存放静态的数据。<strong>初始化只在类加载的时候执行一次</strong>。</p>
<p>类的实例化：是指创建一个对象的过程。这个过程中会在堆中开辟内存，将一些非静态的方法，变量存放在里面。在程序执行的过程中，可以创建多个对象，既多次实例化。每次实例化都会开辟一块新的内存。</p>
<h2 id="TCP发送报文发生粘包问题解决方案"><a href="#TCP发送报文发生粘包问题解决方案" class="headerlink" title="TCP发送报文发生粘包问题解决方案"></a><strong>TCP发送报文发生粘包问题解决方案</strong></h2><ol>
<li><p>发送固定长度的消息</p>
</li>
<li><p>包结尾增加分隔符</p>
</li>
<li><p>把消息分成消息头和消息体，其中消息头上包含长度</p>
</li>
</ol>
<h2 id="最大公约数和最小公倍数"><a href="#最大公约数和最小公倍数" class="headerlink" title="最大公约数和最小公倍数"></a><strong>最大公约数和最小公倍数</strong></h2><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> a,b;</span><br><span class="line"><span class="keyword">int</span> small = a&lt;b?a:b;<span class="comment">//a和b的最小数</span></span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">int</span> i=small;i&gt;=<span class="number">1</span>;i--) &#123;</span><br><span class="line">    <span class="keyword">if</span>(a%i==<span class="number">0</span> &amp;&amp; b%i==<span class="number">0</span>) &#123;</span><br><span class="line">        System.out.<span class="keyword">println</span>(<span class="string">&quot;最大公约数：&quot;</span>+i);</span><br><span class="line">        System.out.<span class="keyword">println</span>(<span class="string">&quot;最小公倍数：&quot;</span>+(i*(a<span class="regexp">/i)*(b/i</span>)));</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

    </div>

    
    
    

      <footer class="post-footer">
          <div class="post-tags">
              <a href="/wang-cheng/tags/%E9%9D%A2%E8%AF%95%E9%A2%98/" rel="tag"># 面试题</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/wang-cheng/2022/03/20/%E9%9D%A2%E8%AF%95%E9%A2%98-%E5%9B%9B/" rel="prev" title="面试题(四)">
      <i class="fa fa-chevron-left"></i> 面试题(四)
    </a></div>
      <div class="post-nav-item">
    <a href="/wang-cheng/2022/03/23/%E9%9D%A2%E8%AF%95%E9%A2%98-%E5%85%AD/" rel="next" title="面试题(六)">
      面试题(六) <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#Spring%E4%BA%8B%E5%8A%A1%E7%9A%84%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F%E5%92%8C%E5%8E%9F%E7%90%86%E4%BB%A5%E5%8F%8A%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB"><span class="nav-number">1.</span> <span class="nav-text">Spring事务的实现方式和原理以及隔离级别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%84%8F%E8%AF%BB%E3%80%81%E4%B8%8D%E5%8F%AF%E9%87%8D%E5%A4%8D%E8%AF%BB%E3%80%81%E5%B9%BB%E8%AF%BB"><span class="nav-number">2.</span> <span class="nav-text">脏读、不可重复读、幻读</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#MySQL%E5%9B%9B%E7%A7%8D%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB"><span class="nav-number">3.</span> <span class="nav-text">MySQL四种隔离级别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Spring%E4%BA%8B%E5%8A%A1%E4%BC%A0%E6%92%AD%E6%9C%BA%E5%88%B6"><span class="nav-number">4.</span> <span class="nav-text">Spring事务传播机制</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Spring%E4%BA%8B%E5%8A%A1%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E4%BC%9A%E5%A4%B1%E6%95%88"><span class="nav-number">5.</span> <span class="nav-text">Spring事务什么时候会失效</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BB%80%E4%B9%88%E6%98%AFbean%E7%9A%84%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D%EF%BC%8C%E6%9C%89%E5%93%AA%E4%BA%9B%E6%96%B9%E5%BC%8F"><span class="nav-number">6.</span> <span class="nav-text">什么是bean的自动装配，有哪些方式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Spring-Boot%E3%80%81SpringMVC%E5%92%8CSpring%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB"><span class="nav-number">7.</span> <span class="nav-text">Spring Boot、SpringMVC和Spring有什么区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Spring-MVC%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B"><span class="nav-number">8.</span> <span class="nav-text">Spring MVC工作流程</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#SpringMVC%E7%9A%84%E4%B8%BB%E8%A6%81%E7%BB%84%E4%BB%B6-%E4%B9%9D%E5%A4%A7%E7%BB%84%E4%BB%B6"><span class="nav-number">9.</span> <span class="nav-text">SpringMVC的主要组件(九大组件)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Spring-Boot%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E5%8E%9F%E7%90%86"><span class="nav-number">10.</span> <span class="nav-text">Spring Boot自动配置原理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A6%82%E4%BD%95%E7%90%86%E8%A7%A3SpringBoot%E4%B8%AD%E7%9A%84Starter"><span class="nav-number">11.</span> <span class="nav-text">如何理解SpringBoot中的Starter</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF%E5%B5%8C%E5%85%A5%E5%BC%8F%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E4%BD%BF%E7%94%A8%E5%B5%8C%E5%85%A5%E5%BC%8F%E6%9C%8D%E5%8A%A1%E5%99%A8"><span class="nav-number">12.</span> <span class="nav-text">什么是嵌入式服务器，为什么要使用嵌入式服务器</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Jar%E5%8C%85%E5%92%8CWar%E5%8C%85%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-number">13.</span> <span class="nav-text">Jar包和War包的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#SSRF"><span class="nav-number">14.</span> <span class="nav-text">SSRF</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#CSRF"><span class="nav-number">15.</span> <span class="nav-text">CSRF</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#AOP%E4%B8%AD%E6%9C%AF%E8%AF%AD%E6%8F%8F%E8%BF%B0"><span class="nav-number">16.</span> <span class="nav-text">AOP中术语描述</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#GC%E4%B8%AD%E7%9A%84%E6%96%B0%E7%94%9F%E4%BB%A3%E3%80%81%E8%80%81%E5%B9%B4%E4%BB%A3%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8"><span class="nav-number">17.</span> <span class="nav-text">GC中的新生代、老年代垃圾收集器</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Java%E7%A8%8B%E5%BA%8F%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%89%E4%B8%AA%E5%8E%9F%E5%88%99"><span class="nav-number">18.</span> <span class="nav-text">Java程序初始化三个原则</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Java%E5%88%9D%E5%A7%8B%E5%8C%96-%E7%B1%BB%E5%8A%A0%E8%BD%BD-%E9%A1%BA%E5%BA%8F"><span class="nav-number">19.</span> <span class="nav-text">Java初始化(类加载)顺序</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#java%E7%B1%BB%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%E5%92%8C%E5%AE%9E%E4%BE%8B%E5%8C%96%E5%8C%BA%E5%88%AB"><span class="nav-number">20.</span> <span class="nav-text">java类的初始化和实例化区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#TCP%E5%8F%91%E9%80%81%E6%8A%A5%E6%96%87%E5%8F%91%E7%94%9F%E7%B2%98%E5%8C%85%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88"><span class="nav-number">21.</span> <span class="nav-text">TCP发送报文发生粘包问题解决方案</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9C%80%E5%A4%A7%E5%85%AC%E7%BA%A6%E6%95%B0%E5%92%8C%E6%9C%80%E5%B0%8F%E5%85%AC%E5%80%8D%E6%95%B0"><span class="nav-number">22.</span> <span class="nav-text">最大公约数和最小公倍数</span></a></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">王诚</p>
  <div class="site-description" itemprop="description">命运对勇士低语，你无法抵御风暴；勇士低声回应，我就是风暴</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/wang-cheng/archives/">
        
          <span class="site-state-item-count">32</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/wang-cheng/tags/">
          
        <span class="site-state-item-count">12</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">王诚</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Gemini</a> 强力驱动
  </div>

        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>








      </div>
    </footer>
  </div>

  
  <script src="/wang-cheng/lib/anime.min.js"></script>
  <script src="/wang-cheng/lib/velocity/velocity.min.js"></script>
  <script src="/wang-cheng/lib/velocity/velocity.ui.min.js"></script>

<script src="/wang-cheng/js/utils.js"></script>

<script src="/wang-cheng/js/motion.js"></script>


<script src="/wang-cheng/js/schemes/pisces.js"></script>


<script src="/wang-cheng/js/next-boot.js"></script>




  















  

  

  

</body>
</html>
